#ifndef SRC_BASE_ASYNC_SOCKET_H_
#define SRC_BASE_ASYNC_SOCKET_H_

#include "base/event_loop.h"
#include "base/sigslot.h"
#include "event2/buffer.h"
#include "event2/bufferevent.h"

class AsyncSocket : public noncopyable,
  public std::enable_shared_from_this<AsyncSocket> {
 public:
  typedef std::shared_ptr<AsyncSocket> Ptr;
  explicit AsyncSocket(EventLoop::Ptr event_loop, evutil_socket_t fd = -1);
  virtual ~AsyncSocket();

 public:
  sigslot::signal1<AsyncSocket::Ptr> SignalConnected;
  sigslot::signal4<AsyncSocket::Ptr,
          uint16_t,
          const char *,
          uint32_t> SignalPacket;
  sigslot::signal2<AsyncSocket::Ptr, int> SignalError;
  sigslot::signal1<AsyncSocket::Ptr> SignalClosed;

 public:
  bool Initialize();
  bool AsyncConnect(const std::string &ip, int port);
  void AsyncSend(uint16_t cmd, const char *data, uint32_t data_size);

  void OnRead(struct bufferevent *bev);
  void OnEvent(struct bufferevent *bev, int16_t events);

 private:
  EventLoop::Ptr event_loop_;
  evutil_socket_t fd_;
  struct bufferevent *bev_;
  struct PacketHeader header_;
  char recv_buffer_[MAX_BUFFER_SIZE];
  uint32_t recv_size_;
};

#endif  // SRC_BASE_ASYNC_SOCKET_H_
